package model;

import java.io.Serializable;
import model.playingfield.PlayingField;


/**
 * @author christopher
 * This is the State. It represents the state of the game at any
 * point in time, and records, specifically: 
 * 
 * Regarding the players:
 * 		what players are currently playing the game 
 * 		where their pieces are 
 * 		whose turn it is to make a move
 * 
 * Regarding the game:
 * 		If the game is still running
 * 		what settings are in effect
 * 		 	Is music enabled?
 * 			Are sound effects enabled?
 */
public class State implements IState, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 *  Players currently playing. Null indicates that the player is no longer in game.
	 */
	private Player[] players;

	/**
	 * A representation of the playingfield	
	 */
	private PlayingField playingfield;

	/**
	 * Statistics for the game in progress
	 */
	private Statistics statistics;

	/**
	 * The following are state variables, used in order to determine what phase
	 * of a players turn the Model currently is in, and data related to it:
	 *   - playerSelected : a player is currently selected
	 *   - dieRolled      : the die has been rolled
	 *   - spotSelected   : a piece has been selected
	 *   - moveMade 	  : the move has been made
	 *   - gameInProgress : whether or not the game is currently in progress
	 *   
	 *   - currentPlayer  : the Player which the current turn belongs to
	 *   - currentDieValue : the result of the current players die throw
	 */	 
	private boolean playerSelected  = false;
	private boolean dieRolled	    = false;
	private boolean spotSelected    = false;
	private boolean moveMade 	    = false;
	private boolean gameInProgress  = false;
	private Integer currentPlayer   = 0;
	private int	    currentDieValue = 0;    

	/**
	 * The constructor simply initiates the core data structures, which are passed down
	 * from upstread. All state variables will be set to their standard null (or equivalent)
	 * values by default.
	 * @param players
	 * @param playingfield
	 * @param statistics
	 */
	public State(Player[] players, PlayingField playingfield, Statistics statistics) {
		this.players = players;
		this.playingfield = playingfield;
		this.statistics = statistics;
	}

	public State() {
	}

	/**
	 * remove a player from the game, for example, in the event 
	 * that he or she is booted from the game for some reason.
	 */
	@Override
	public void removePlayer(Player player) {
		/**
		 * First is to remove the Player from the 
		 * HashMap. 
		 * 
		 * Then it should go to playerfield, and remove the 
		 * the players pieces, change their locations to null.  
		 * 
		 */

		//Remove the player
		for(int i = 0; i < players.length-1; i++){
			if(players[i] == player){
				players[i] = null;
			}
		}  

		//Remove all pieces corresponding to that player at the field
			for(int k=0; k < playingfield.getPieceLocations().length-1; k++){
				Integer[][] list = playingfield.getPieceLocations();
				if(list[player.getID()][k] != null){
					list[player.getID()][k] = null;
				}
			}
	} 


	/*
	 * The following are various getters and setters
	 */

	/**
	 * @return a specific player
	 */
	public Player getPlayer(int player) {
		return players[player];
	}
	
	/**
	 * For testing propose 
	 * Checks if there is players into the game
	 * @param players
	 * @return
	 */
	public boolean hasPlayers(Player[] players){
		boolean hasPlayers = false;
		for(int i=0; i < players.length; i++){
			if(players[i] != null){
				hasPlayers = true;
				return hasPlayers;
			}
		}
		return hasPlayers;
	}

	/**
	 * @param players the players to set
	 */
	public void setPlayers(Player[] players) {
		this.players = players;
	}


	/**
	 * @return the dieRolled
	 */
	@Override
	public boolean isDieRolled() {
		return dieRolled;
	}

	/**
	 * @param dieRolled the dieRolled to set
	 */
	@Override
	public void setDieRolled(boolean dieRolled) {
		this.dieRolled = dieRolled;
	}

	/**
	 * @return the spotSelected
	 */
	@Override
	public boolean hasMoved() {
		return spotSelected;
	}

	/**
	 * @param spotSelected the spotSelected to set
	 */
	@Override
	public void setSpotSelected(boolean spotSelected) {
		this.spotSelected = spotSelected;
	}

	/**
	 * @return the currentDieValue
	 */
	public int getCurrentDieValue() {
		return currentDieValue;
	}

	/**
	 * @param currentDieValue the currentDieValue to set
	 */
	public void setCurrentDieValue(int currentDieValue) {
		this.currentDieValue = currentDieValue;
	}

	/**
	 * @return the moveMade
	 */
	@Override
	public boolean isMoveMade() {
		return moveMade;
	}

	/**
	 * @param moveMade the moveMade to set
	 */
	@Override
	public void setMoveMade(boolean moveMade) {
		this.moveMade = moveMade;
	}

	/**
	 * @return the currentPlayer
	 */
	@Override
	public Integer getCurrentPlayer() {
		return currentPlayer;
	}

	/**
	 * @param currentPlayer the currentPlayer to set
	 */
	@Override
	public void setCurrentPlayer(Integer currentPlayer) {
		this.currentPlayer = currentPlayer;
		System.out.println("STATE: currentplaye is " + this.currentPlayer);
	}	

	/**
	 * Return locations of player pieces. 
	 */
	@Override
	public Integer[][] getPlayerLocations() {
		return playingfield.getPieceLocations();
	}


	/**
	 * @param playerSelected the playerSelected to set
	 */
	public void setPlayerSelected(boolean playerSelected) {
		this.playerSelected = playerSelected;
	}

	/**
	 * @return the playerSelected
	 */
	public boolean isPlayerSelected() {
		return playerSelected;
	}

	/**
	 * @return the gameInProgress
	 */
	public boolean isGameInProgress() {
		return gameInProgress;
	}

	/**
	 * @param gameInProgress the gameInProgress to set
	 */
	public void setGameInProgress(boolean gameInProgress) {
		this.gameInProgress = gameInProgress;
	}

	@Override
	public void resetStateVars() {

		playerSelected = false;
		dieRolled = 	 false;
		spotSelected = 	 false;
		moveMade = 		 false;

		currentPlayer =  null;
		currentDieValue = 0;
	}

	@Override
	public PlayingField getPlayingField() {

		return playingfield;
	}

	//	public void setPieceLocation(Player player, Integer location){
	//		for(int i = 0; i <= players.size(); i++){
	//		if(players.get(i))
	//		}
	//		getPlayingField().getPieceLocations().put(player, value));
	//	}


	@Override
	public Statistics[] getStatistics() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getNumOfPlayers() {
		// TODO Auto-generated method stub
		return players.length;
	}

	Battle battle; //Should probably not be in State
	@Override
	public void setBattle(Battle b) {
			battle = b;
	}

	@Override
	public Battle getBattle() {
		return battle;
	}	
}